#pragma once

///////////////////////////////////////////////////////////////
//ObjectEntity will generated from Rawentity or Rawentity list
//It will map all record into object maps, right now, this is 
//done by providing specific functions
///////////////////////////////////////////////////////////////

#include <string>
#include <list>
#include <memory>
#include <boost/date_time.hpp>

class DataBaseAccessObject;
struct RawEntityFeed;
struct RawEntityAlert;
struct RawEntityRule;
struct RawEntityFeedRule;

//Super class for all entity object
class EntityObject
{
public:
    virtual ~EntityObject(){}
};

typedef std::weak_ptr< EntityObject > EntityWeakPtr;
typedef std::shared_ptr< EntityObject> EntitySmtPtr;

class AlertObject;
class FeedRuleObject;
class RuleObject;

class FeedObject : public EntityObject
{

public: //Right now, nothing too much fancy, so make all fields public.. Fix in future
    int         m_id;
    std::string m_name;
    std::string m_description;
    std::string m_pnacPrefix;
    std::string m_attribution;
    int         m_alertStatus;
    std::string m_emailList;
    std::list< RuleObject* > m_rules; //The object will be stored in a global array, which will be 
                                      //Deallocated after all work done
    std::list< FeedRuleObject* > m_feedRules; //All alert can be found from this list

    void        PopulateFromEntity( RawEntityFeed& rawEntity );
    void        UpdateToDataBase( DataBaseAccessObject& dao ); //Right now, only update the feed's status
};

class RuleObject : public EntityObject
{
public:
    int         m_id;
    std::string m_name;
    std::string m_description;
    std::string m_format;

    void        PopulateFromEntity( RawEntityRule& rawEntity );
    void        UpdateToDataBase(); //Not implemented, if any one called this, will not compile
};

class FeedRuleObject : public EntityObject
{
public:
    int         m_id;
    int         m_feedId;
    int         m_ruleId;
    std::string m_value;
    int         m_alertStatus;

    std::list< AlertObject* > m_alerts;

    void        PopulateFromEntity( RawEntityFeedRule& rawEntity );
    void        UpdateToDataBase( DataBaseAccessObject& dao ); //Only update the feedrule's id
};

class AlertObject : public EntityObject
{
public:
    int         m_id;
    int         m_feedRuleId;
    boost::posix_time::ptime m_createTime;
    std::string m_message;
    int         m_alertStatus;
    int         m_flag;

    void        PopulateFromEntity( RawEntityAlert& rawEntity );
    void        UpdateToDataBase( DataBaseAccessObject& dao ); //Only update the alert's flag
};


////////////////////////////////////////////////////////////////
//Currently, used for generate entities
////////////////////////////////////////////////////////////////
class EntityManager 
{
public:
    static EntityManager* Instance()
    {
        static EntityManager manager;
        return &manager;
    }

    template< typename _Ty >
    _Ty* CreateObject()
    {
        try
        {
            std::shared_ptr<_Ty> ob( new _Ty );
            m_entityStorage.push_back( ob );
            return ob.get();
        }
        catch(...)
        {
            return NULL;
        }
    }


    void PushBack( EntitySmtPtr entity ){ m_entityStorage.push_back( entity ); }

    void Reset(){ m_entityStorage.clear(); }

    void GetFullFeedRuleAlertList( DataBaseAccessObject& dao, std::list< FeedObject* >& feedList ); //
    
private:
    std::list< EntitySmtPtr > m_entityStorage; //The storage for all entitieis
};
